﻿using System.Collections;
using System.IO;
using System.Reflection;
using NUnit.Framework;

namespace Salient.IO.Tests
{
    /// <copyright file="ResourceLocator.cs" author="Sky Sanders">
    ///
    /// Public Domain "License"
    /// 
    /// I, Sky Sanders, single-handedly wrote the code in this file, and as the legal author 
    /// (it was not a "work for hire") have placed it in the public domain.
    /// 
    /// That means I have disclaimed copyright of it. 
    /// 
    /// It also means that you may take the source code and use it for any purpose, commercial 
    /// or non-commercial, copyrighted, open-source, Free, free, or public domain, with no legal 
    /// obligation to acknowledge the borrowing/copying in any way. 
    /// 
    /// That said; attribution and/or feedback is always appreciated.
    ///
    /// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
    /// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    /// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    /// PARTICULAR PURPOSE.
    ///
    /// </copyright>
    /// <version>1.0</version>
    /// <author>Sky Sanders</author>
    /// <web>http://spikes.codeplex.com</web>
    /// <email>sky.sanders@gmail.com</email>
    /// <date>2010-01-19</date>
    /// 
    /// <summary>
    /// the tests in this file exercise Salient.IO.ResourceLocator
    /// </summary>
    [TestFixture]
    public class ResourceLocatorFixture
    {

        //

        private const string path_binaryFile = @"Resources\BinaryFile.sdf";
        private const string path_textFile = @"Resources\TextFile.txt";
        private const string path_textFileWhackSeperator = @"Resources/TextFile.txt";

        private const string path_binaryFileUNC = @"\\SKY_TP\ResourceLocatorTest\Resources\BinaryFile.sdf";
        private const string path_textFileUNC = @"\\SKY_TP\ResourceLocatorTest\Resources\TextFile.txt";
        

        private const string path_binaryAssembly = "res://*/Salient.IO.Tests.Resources.BinaryResource.sdf";
        private const string path_textAssembly = "res://*/Salient.IO.Tests.Resources.TextResource.txt";

        private const string path_binaryAbsoluteAssembly = "res://Salient.IO.ResourceLocator.Tests/Salient.IO.Tests.Resources.BinaryResource.sdf";
        private const string path_textAbsoluteAssembly = "res://Salient.IO.ResourceLocator.Tests/Salient.IO.Tests.Resources.TextResource.txt";


        private const string path_binaryFile_bad = "cc.sdf";
        private const string path_textFile_bad = "cc.txt";

        private const string path_binaryAssembly_bad = "res://ssdfsdfsdf";
        private const string path_textAssembly_bad = "res://*/cc.txt";

        private const string path_binaryAbsoluteAssembly_bad = "res://cc/Salient.IO.Tests.BinaryResource.sdf";
        private const string path_textAbsoluteAssembly_bad = "res://cc/Salient.IO.Tests.TextResource.txt";

        [Test]
        public void EnsureItemsAreCached()
        {
            // clear the cache, it is static after all
            FieldInfo finfo = typeof (ResourceLocator).GetField("_cache", BindingFlags.NonPublic | BindingFlags.Static);
            Assert.IsNotNull(finfo, "could not get field reference");
            Hashtable cache = (Hashtable) finfo.GetValue(null);
            Assert.IsNotNull(cache, "coudl not get cache reference");
            cache.Clear();
            Assert.AreEqual(0, cache.Count);
            string resource = ResourceLocator.GetTextResource(path_textFile);
            Assert.IsNotNull(resource, "resource is null");
            Assert.AreEqual("file", resource);
            Assert.AreEqual(1, cache.Count);
            resource = ResourceLocator.GetTextResource(path_textFile);
            Assert.AreEqual(1, cache.Count);
        }

        [Test]
        public void GetBinaryAssemblyResource()
        {
            byte[] resource = ResourceLocator.GetResource(path_binaryAssembly);
            Assert.IsNotNull(resource);
        }

        [Test]
        public void GetBinaryAssemblyResourceAbsolute()
        {
            byte[] resource = ResourceLocator.GetResource(path_binaryAbsoluteAssembly);
            Assert.IsNotNull(resource);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetBinaryAssemblyResourceAbsoluteBad()
        {
            ResourceLocator.GetResource(path_binaryAbsoluteAssembly_bad);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetBinaryAssemblyResourceBad()
        {
            ResourceLocator.GetResource(path_binaryAssembly_bad);
        }

        [Test]
        public void GetBinaryFileResource()
        {
            byte[] resource = ResourceLocator.GetResource(path_binaryFile);
            Assert.IsNotNull(resource);
        }

        [Test]
        public void GetBinaryFileResourceUNC()
        {
            byte[] resource = ResourceLocator.GetResource(path_binaryFileUNC);
            Assert.IsNotNull(resource);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetBinaryFileResourceBad()
        {
            ResourceLocator.GetResource(path_binaryFile_bad);
        }

        [Test]
        public void GetTextAssemblyResource()
        {
            string resource = ResourceLocator.GetTextResource(path_textAssembly);
            Assert.IsNotNull(resource);
            Assert.AreEqual("assembly", resource);
        }

        [Test]
        public void GetTextAssemblyResourceAbsolute()
        {
            string resource = ResourceLocator.GetTextResource(path_textAbsoluteAssembly);
            Assert.IsNotNull(resource);
            Assert.AreEqual("assembly", resource);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetTextAssemblyResourceAbsoluteBad()
        {
            ResourceLocator.GetTextResource(path_textAbsoluteAssembly_bad);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetTextAssemblyResourceBad()
        {
            ResourceLocator.GetTextResource(path_textAssembly_bad);
        }

        [Test]
        public void GetTextFileResource()
        {
            string resource = ResourceLocator.GetTextResource(path_textFile);
            Assert.IsNotNull(resource);
            Assert.AreEqual("file", resource);
        }
        [Test]
        public void GetTextFileResourceUNC()
        {
            string resource = ResourceLocator.GetTextResource(path_textFileUNC);
            Assert.IsNotNull(resource);
            Assert.AreEqual("file", resource);
        }
        [Test]
        public void GetTextFileResourceAbsolutePath()
        {
            string fullPath = Path.GetFullPath(path_textFile);
            string resource = ResourceLocator.GetTextResource(fullPath);
            Assert.IsNotNull(resource);
            Assert.AreEqual("file", resource);
        }

        [Test, ExpectedException(typeof (FileNotFoundException))]
        public void GetTextFileResourceBad()
        {
            ResourceLocator.GetTextResource(path_textFile_bad);
        }

        [Test]
        public void GetTextFileResourceWhackSeperator()
        {
            string resource = ResourceLocator.GetTextResource(path_textFileWhackSeperator);
            Assert.IsNotNull(resource);
            Assert.AreEqual("file", resource);
        }
    }
}